<?php

class MsggSubmail extends MsggChannelBase
{

    use util_array;
    //10 minutes
    const SMS_TIMEOUT_TIME = 600;
    const REST_URL = 'https://api.mysubmail.com';
    const SMS_REST = 'message/xsend';
    const SMS_LOG_REST = 'log/message';
    const SUCCESS_RESP = 'success';

    const TYPE_SMS = 'sms';

    const  CONFIG_APPID = 'app_id';
    const  CONFIG_APP_KEY = 'app_key';
    const  VARS_PRE = 'var';

    const ERROR_CODE_FAIL = 1;

    private static $_conf = array();

    public static function sms($params = array(), $conf = array())
    {
        static::$_conf = $conf;
        $result = array('code' => 0, 'msg' => '', 'data' => array(), 'ext' => array());
        //replace some invalid character
        if (isset($params['param']) && is_array($params['param'])) {
            foreach ($params['param'] as $key => $param) {
                $params['param'][$key] = str_replace(',', '，', $params['param'][$key]);
                $params['param'][$key] = str_replace(['【', '】'], ['【' => '（', '】' => '）'], $params['param'][$key]);
            }
        }
        try {
            $vars = self::getVars($params);
            //curl api
            $url = self::getUrl(self::TYPE_SMS);
            $postdata = array(
                'appid' => static::getConf(self::CONFIG_APPID),
                'to' => $params['phone'],
                'project' => $params['template']['id_submail'],
                'vars' => json_encode($vars),
                'signature' => self::getConf(self::CONFIG_APP_KEY)
            );
            $resp = self::curlApi($url, $postdata);
            $result['data'] = $resp;
            $result['ext']['id'] = empty($resp['send_id']) ? null : $resp['send_id'];
            $result['ext']['status'] = MsggSms::STATUS_RUNNING;
        } catch (Exception $e) {
            $result['code'] = $e->getCode();
            $result['msg'] = $e->getMessage();
            $result['ext']['status'] = MsggSms::STATUS_ERROR;
        }
        $result['ext']['class'] = self::class;
        return $result;
    }

    private static function curlApi($url, $postdata = array(), $options = array())
    {
        try {
            $headers = array(
                'Accept' => 'application/json;',
                'Content-Type' => 'application/json;charset=utf-8;',
            );
            $try = self::getConf('try', 2);
            while ($try) {
                $try--;
                $cres = Curl::post($url, json_encode($postdata, JSON_UNESCAPED_UNICODE), $options, $headers);
                if ($cres['err']) {
                    if ($try) {
                        continue;
                    }
                    throw new Exception('CurlErr:' . $cres['err'], self::ERROR_CODE_FAIL);
                }
                if (empty($cres['content'])) {
                    if ($try) {
                        continue;
                    }
                    throw new Exception('response content empty', self::ERROR_CODE_FAIL);
                }
                if (!($resp = json_decode($cres['content'], true))) {
                    if ($try) {
                        continue;
                    }
                    throw new Exception('response content decode fail:' . $cres['content'], self::ERROR_CODE_FAIL);
                }
                $status = isset($resp['status']) ? $resp['status'] : 'null';
                if ($status != self::SUCCESS_RESP) {
                    if ($try) {
                        continue;
                    }
                    throw new Exception('response status abnormal:' . $cres['content'], self::ERROR_CODE_FAIL);
                }
                return $resp;
            }
        } catch (Exception $e) {
            throw new Exception($e->getMessage(), self::ERROR_CODE_FAIL);
        }
    }

    public static function getVars($params)
    {
        $vars = array();
        $param = $params['param'];
        $i = 1;
        foreach ($param as $val) {
            $key = (self::VARS_PRE . $i);
            $vars[$key] = $val;
            $i++;
        }
        return $vars;
    }

    private static function getUrl($type = self::TYPE_SMS)
    {
        switch ($type) {
            case self::TYPE_SMS:
            default:
                return self::REST_URL . "/" . self::SMS_REST;
                break;
        }
    }

    public static function getConf($name, $default = null)
    {
        return isset(static::$_conf[$name]) ? static::$_conf[$name] : $default;
    }

    public static function hookSms()
    {
        $params = $_POST;
        if (($ext_id = self::util_array_get($params, 'send_id', null)) == null) {
            return;
        }
        Yii::log(json_encode($params), CLogger::LEVEL_INFO, 'submail.hook');
        if (($status = self::util_array_get($params, 'events', null)) === null) {
            return;
        }
        if (!($ext_status = self::mapStatus(self::TYPE_SMS, $status))) {
            return;
        }
        if (MsggChannelLog::updateExtStatus($ext_id, $ext_status, $params)) {
            echo '';
        }
    }

    private static function mapStatus($type, $status)
    {
        $resStatus = null;
        switch ($type) {
            case self::TYPE_SMS:
                switch ($status) {
                    case 'request':
                    case 'sending':
                        $resStatus = MsggSms::STATUS_RUNNING;
                        break;
                    case 'delivered':
                        $resStatus = MsggSms::STATUS_SUCCESS;
                        break;
                    case 'dropped':
                    case 'unkown':
                    default:
                        $resStatus = MsggSms::STATUS_FAILURE;
                        break;
                }
                break;
        }
        return $resStatus;
    }

    public static function refreshStatus(MsggChannelLog $channelLog)
    {
        // TODO: Implement refreshStatus() method.
        if (empty($channelLog)) {
            return 'error';
        }
        switch ($channelLog->type) {
            case MsggItem::TYPE_SMS:
                $config = json_decode($channelLog->conf, true);
                $url = MsggSubmail::REST_URL . "/" . MsggSubmail::SMS_LOG_REST;
                $appid = $config[MsggSubmail::CONFIG_APPID];
                $appkey = $config[MsggSubmail::CONFIG_APP_KEY];
                $params = $channelLog->getParams();
                $respon = Curl::post($url, [
                    'appid' => $appid,
                    'signature' => $appkey,
                    'recipient' => $params['phone'],
                    'start_date' => $channelLog->time - 3600,
                    'end_date' => $channelLog->time + 3600
                ]);
                $contents = json_decode($respon['content'], true);
                $results = self::util_array_get($contents, 'results', []);
                $status = $channelLog->ext_status;
                foreach ($results as $result) {
                    if ($channelLog->ext_id == $result['send_id']) {
                        $status = self::mapStatus(self::TYPE_SMS, $result['result_status']);
                        return $status;
                    }
                }
                if (time() - $channelLog->time >= self::SMS_TIMEOUT_TIME) {
                    Yii::log('time out ' . $channelLog->id, CLogger::LEVEL_ERROR,   __METHOD__);
                    return MsggSms::STATUS_FAILURE;
                }
                return $status;
                break;
        }
        return parent::refreshStatus($channelLog);
    }
}